package titan.wizards.newTitanProject;

import java.io.File;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import titan.messages.Messages;
import titan.utils.Database;
import titan.utils.StatusBar;
import titan.utils.TextValidator;
import titan.utils.TitanUtils;
import titan.wizards.BaseTitanPage;

/**
 *  At this page, the database configuration can be set. The attributes are:
 *  DBMS, host, database name, user, password and port to access database and database schema
 *  that Titan application will use.
 *  It's possible to import to the specified host the database structure of a Titan application
 */
public class DataBasePage extends BaseTitanPage {
	Combo sgbd;
	Text host;
	Text name;
	Text user;
	Text port;
	Text password;
	Text schema;
	//Internal data
	private Button importButton;
	//Status
	IStatus sgbdStatus;
	IStatus hostStatus;
	IStatus nameStatus;
	IStatus userStatus;
	IStatus portStatus;
	IStatus schemaStatus;

	protected DataBasePage() {
		super(Messages.DBConfiguration);
		setTitle(Messages.DBConfiguration);
		setDescription(Messages.DataBasePage_desc);
		IStatus status = new Status(IStatus.OK, "default", ""); //$NON-NLS-1$ //$NON-NLS-2$
		hostStatus = sgbdStatus = nameStatus = userStatus = portStatus = schemaStatus = status;
	}

	/**
	 * {@inheritDoc}
	 */
	public void createControl(Composite parent) {
		Composite composite = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout(2, false);
		layout.verticalSpacing = 12;
		composite.setLayout(layout);
		setControl(composite);

		MouseTrackAdapter mouseExit = new MouseTrackAdapter() {
			public void mouseExit(MouseEvent e) {
			    applyStatus(pageStatus);
			}
		};

		new Label(composite, SWT.NONE).setText(Messages.DBMS+":"); //$NON-NLS-1$
		sgbd = new Combo(composite, SWT.READ_ONLY);
		GridData gd = new GridData(350, 13);
		gd.horizontalAlignment = SWT.FILL;
		sgbd.setLayoutData(gd);
		sgbd.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent event) {
				updateButtons();
			}
		});
		sgbd.addListener(SWT.MouseEnter, new Listener () {
			public void handleEvent(Event e) {
			    applyStatus(new Status(IStatus.INFO, "sgbd", Messages.DBMS_desc) ); //$NON-NLS-1$
			}
		});
		sgbd.addMouseTrackListener(mouseExit);
		try {
			String[] sgbdArray = TitanUtils.getSgbdList();
			for(int i = 0; i < sgbdArray.length; i++)
				sgbd.add(sgbdArray[i]);
		} catch (Exception e) {
			applyStatus(new Status(IStatus.ERROR, "sgbd", e.getMessage()) ); //$NON-NLS-1$
		}

		new Label(composite, SWT.NONE).setText(Messages.Host+":"); //$NON-NLS-1$
		host = new Text(composite, SWT.BORDER | SWT.SINGLE);
		gd = new GridData();
		gd.horizontalAlignment = SWT.FILL;
		host.setLayoutData(gd);
		host.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent event) {
				IStatus status = new Status(IStatus.OK, "host", ""); //$NON-NLS-1$ //$NON-NLS-2$
				if(!host.getText().isEmpty()) { //$NON-NLS-1$
					if(!TextValidator.isValidHost(host.getText()))
						status = new Status(IStatus.ERROR, "host", //$NON-NLS-1$
								Messages.InvalidValue+Messages.Host_ext);
				}
				applyStatus(status);
				updateButtons();
			}
		});
		host.addListener(SWT.MouseEnter, new Listener () {
			public void handleEvent(Event e) {
			    applyStatus(new Status(IStatus.INFO, "host", Messages.Host_desc) ); //$NON-NLS-1$
			}
		});
		host.addMouseTrackListener(mouseExit);
		host.setText("localhost"); //$NON-NLS-1$

		new Label(composite, SWT.NONE).setText(Messages.DBName+":"); //$NON-NLS-1$
		name = new Text(composite, SWT.BORDER | SWT.SINGLE);
		gd = new GridData();
		gd.horizontalAlignment = SWT.FILL;
		name.setLayoutData(gd);
		name.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent event) {
				Status status = new Status(IStatus.OK, "name", ""); //$NON-NLS-1$ //$NON-NLS-2$
				if(!name.getText().isEmpty()) { //$NON-NLS-1$
					if(!TextValidator.isValidUObject(name.getText()))
						status = new Status(IStatus.ERROR, "name", //$NON-NLS-1$
								Messages.InvalidValue+Messages.DataBase_ext);
				}
				applyStatus(status);
				updateButtons();
			}
		});
		name.addListener(SWT.MouseEnter, new Listener () {
			public void handleEvent(Event e) {
			    applyStatus(new Status(IStatus.INFO, "name", Messages.DBName_desc) ); //$NON-NLS-1$
			}
		});
		name.addMouseTrackListener(mouseExit);

		new Label(composite, SWT.NONE).setText(Messages.User+":"); //$NON-NLS-1$
		user = new Text(composite, SWT.BORDER | SWT.SINGLE);
		gd = new GridData();
		gd.horizontalAlignment = SWT.FILL;
		user.setLayoutData(gd);
		user.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent event) {
				Status status = new Status(IStatus.OK, "user", ""); //$NON-NLS-1$ //$NON-NLS-2$
				if(!user.getText().isEmpty()) { //$NON-NLS-1$
					if(!TextValidator.isValidDottedUAlnum(user.getText()))
						status = new Status(IStatus.ERROR, "user", //$NON-NLS-1$
								Messages.InvalidValue+Messages.User_ext);
				}
				applyStatus(status);
				updateButtons();
			}
		});
		user.addListener(SWT.MouseEnter, new Listener () {
			public void handleEvent(Event e) {
			    applyStatus(new Status(IStatus.INFO, "user", Messages.User_desc) ); //$NON-NLS-1$
			}
		});
		user.addMouseTrackListener(mouseExit);

		new Label(composite, SWT.NONE).setText(Messages.Port+":"); //$NON-NLS-1$
		port = new Text(composite, SWT.BORDER | SWT.SINGLE);
		gd = new GridData();
		gd.horizontalAlignment = SWT.FILL;
		port.setLayoutData(gd);
		port.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent event) {
				IStatus status = new Status(IStatus.OK, "port", ""); //$NON-NLS-1$ //$NON-NLS-2$
				if(!port.getText().isEmpty()) { //$NON-NLS-1$
					if(!TextValidator.isValidPort(port.getText()))
						status = new Status(IStatus.ERROR, "port", //$NON-NLS-1$
								Messages.InvalidValue+Messages.Port_ext);
				}
				applyStatus(status);
				updateButtons();
			}
		});
		port.addListener(SWT.MouseEnter, new Listener () {
			public void handleEvent(Event e) {
			    applyStatus(new Status(IStatus.INFO, "port", Messages.Port_desc) ); //$NON-NLS-1$
			}
		});
		port.addMouseTrackListener(mouseExit);
		port.setText("5432"); //$NON-NLS-1$

		new Label(composite, SWT.NONE).setText(Messages.Password+":"); //$NON-NLS-1$
		password = new Text(composite, SWT.BORDER | SWT.SINGLE | SWT.PASSWORD);
		gd = new GridData();
		gd.horizontalAlignment = SWT.FILL;
		password.setLayoutData(gd);
		password.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent event) {
				updateButtons();
			}
		});
		password.addListener(SWT.MouseEnter, new Listener () {
			public void handleEvent(Event e) {
			    applyStatus(new Status(IStatus.INFO, "password", Messages.Password_desc) ); //$NON-NLS-1$
			}
		});
		password.addMouseTrackListener(mouseExit);

		new Label(composite, SWT.NONE).setText("Schema:"); //$NON-NLS-1$
		schema = new Text(composite, SWT.BORDER | SWT.SINGLE);
		gd = new GridData();
		gd.horizontalAlignment = SWT.FILL;
		schema.setLayoutData(gd);
		schema.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent event) {
				Status status = new Status(IStatus.OK, "schema", ""); //$NON-NLS-1$ //$NON-NLS-2$
				if(!schema.getText().isEmpty()) { //$NON-NLS-1$
					if(!TextValidator.isValidUObject(schema.getText()))
						status = new Status(IStatus.ERROR, "schema", //$NON-NLS-1$
								Messages.InvalidValue+Messages.Schema_ext);
				}
				applyStatus(status);
				updateButtons();
			}
		});
		schema.addListener(SWT.MouseEnter, new Listener () {
			public void handleEvent(Event e) {
			    applyStatus(new Status(IStatus.INFO, "schema", Messages.Schema_desc) ); //$NON-NLS-1$
			}
		});
		schema.addMouseTrackListener(mouseExit);
		schema.setText("titan"); //$NON-NLS-1$

		new Label(composite, SWT.NONE);

		importButton = new Button(composite, SWT.PUSH);
		importButton.setText(Messages.ImportDB);
		importButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				StatusBar progressBar = new StatusBar(getShell());
				progressBar.open();
				try {
					//get db.sql file
					File sql = TitanUtils.getDbSql(schema.getText());
					//connect and run the sql
					Database db = new Database(host.getText(), name.getText(), user.getText(),
							port.getText(), password.getText(), sql.getAbsolutePath());
					db.query(progressBar);
				} catch (Exception e) {
					MessageDialog.openError(getShell(), Messages.Error, e.getMessage());
				}
				progressBar.close();
			}
		});
		importButton.addListener(SWT.MouseEnter, new Listener () {
			public void handleEvent(Event e) {
			    applyStatus(new Status(IStatus.INFO, "importButton", Messages.ImportDB_desc) ); //$NON-NLS-1$
			}
		});
		importButton.addMouseTrackListener(mouseExit);
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean canFlipToNextPage() {
		return false;
	}

	/**
	 * Returns whether this page is completed
	 * @return true if the wizard could be finished, and false otherwise
	 */
	public boolean canFinish() {
		if (sgbd == null || pageStatus.getSeverity() == IStatus.ERROR || sgbd.getText().isEmpty() || host.getText().isEmpty() //$NON-NLS-1$ //$NON-NLS-2$
			|| name.getText().isEmpty() || user.getText().isEmpty() || port.getText().isEmpty() //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			|| password.getText().isEmpty() || schema.getText().isEmpty()) { //$NON-NLS-1$ //$NON-NLS-2$
			if(importButton != null)
				importButton.setEnabled(false);
            return false;
		}
		importButton.setEnabled(true);
		return true;
	}

	/**
	 * {@inheritDoc}
	 */
	protected void applyStatus(IStatus new_status) {
		if(new_status.getSeverity() != IStatus.INFO){
			String plugin = new_status.getPlugin();
			if(plugin == "sgbd") //$NON-NLS-1$
				sgbdStatus = new_status;
			else if(plugin == "host") //$NON-NLS-1$
				hostStatus = new_status;
			else if(plugin == "name") //$NON-NLS-1$
				nameStatus = new_status;
			else if(plugin == "user") //$NON-NLS-1$
				userStatus = new_status;
			else if(plugin == "port") //$NON-NLS-1$
				portStatus = new_status;
			else
				schemaStatus = new_status;
		}
		applyPageStatus(new_status);
	}

	/**
	 * {@inheritDoc}
	 */
	protected IStatus greaterStatus() {
		IStatus greater = hostStatus;
		if(greater.getSeverity() < sgbdStatus.getSeverity())
			greater = sgbdStatus;
		if(greater.getSeverity() < nameStatus.getSeverity())
			greater = nameStatus;
		if(greater.getSeverity() < userStatus.getSeverity())
			greater = userStatus;
		if(greater.getSeverity() < portStatus.getSeverity())
			greater = portStatus;
		if(greater.getSeverity() < schemaStatus.getSeverity())
			greater = schemaStatus;
		return greater;
	}
}